package com.personal.datacompare.config;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.personal.core.utils.Assert;
import com.personal.core.utils.CoreUtil;

/**
 * 比较合并DataTable 配置
 * @author cuibo
 *
 */
public class CompareDataTableConfig implements Serializable
{
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    /** 唯一标识 */
    private String id;
    /** 关联Id */
    private String boundId;
    /** 报表名 */
    private String tableName;
    /** 兼容的报表集合 */
    private Set<String> compatibleTableNames;
    /** 标题 */
    private String title;
    /** 对比模式 */
    private String compareMode;
    /** 是否插入不匹配的行数据 */
    private boolean insertNoMatch = true;
    /** 回溯对比(cb20170616先默认是回溯对比) */
    private boolean recall = true;
    /** 左页眉 */
    private String left;
    /** 右页眉 */
    private String right;
    /** 显示列 */
    private List<DisplayColumnConfig> displayColumns;
    /** 判断相等列 */
    private EqualsColumnConfig equalsColumnConfig;
    /** 层级列 */
    private LevelColumnConfig levelColumnConfig;
    /** 比较列 */
    private List<CompareColumnConfig> compareColumnConfigs;
    /** 合并列 */
    private List<CombineColumnConfig> combineColumnConfigs;
    /** 查看列 */
    private List<CheckColumnConfig> checkColumnConfigs;
    /** 查看列 */
    private List<CoverColumnConfig> coverColumnConfigs;
    /** 手动设置的相等情况 */
    private Map<String, Set<String>> handSetEquals;
    /** 是否有差异原因列 */
    private boolean hasDiffReason;
    /** 差异原因列名 */
    private String diffColumnName;
    /** 差异原因显示名 */
    private String diffColumnLabel;
    /** 差异原因key如果为空，则使用使用行号，否则使用两个datarow的这个key的值，使用逗号分隔 */
    private String diffColumnKey;
    /** 标注标红范围 */
    private double labelLevel = Double.MAX_VALUE;
    /** 行列转换 */
    private TransRowColConfig transRowColConfig;
    /** 列循环方式 */
    private ColumnLoopTypeEnum columnLoopType;
    /** 扩展列 */
    private List<ExtendColumnConfig> extendColumnConfigs;
    

    /**
     * 添加手动匹配信息
     * @param valueOne
     * @param valueTwo
     */
    public void addHandSetEquals(String valueOne, String valueTwo)
    {
        if (handSetEquals == null)
        {
            handSetEquals = new HashMap<String, Set<String>>();
        }
        Set<String> sets = handSetEquals.get(valueOne);
        if (sets == null)
        {
            sets = new HashSet<String>();
            handSetEquals.put(valueOne, sets);
        }
        sets.add(valueTwo);
    }

    /**
     * 获取所有为了匹配的列名以及其对应的差异原因列名
     * @return
     */
    public Map<String, String> getAllMatchAndDiffColumnName()
    {
        Map<String, String> result = new LinkedHashMap<String, String>();
        if (equalsColumnConfig != null && !CoreUtil.isEmpty(equalsColumnConfig.getColumnName()))
        {
            result.put(equalsColumnConfig.getColumnName(),
                    CoreUtil.isEmpty(equalsColumnConfig.getDiffColumnName()) ? equalsColumnConfig.getColumnName()
                            : equalsColumnConfig.getDiffColumnName());
        }
        if (levelColumnConfig != null && !CoreUtil.isEmpty(levelColumnConfig.getColumnName()))
        {
            result.put(levelColumnConfig.getColumnName(),
                    CoreUtil.isEmpty(levelColumnConfig.getDiffColumnName()) ? levelColumnConfig.getColumnName()
                            : levelColumnConfig.getDiffColumnName());
        }
        // 使用tableConfig中的结构构建差异原因
        Set<String> otherCols = equalsColumnConfig.getOtherColumnNames();
        if (!CoreUtil.isEmpty(otherCols))
        {
            Set<String> diffCols = equalsColumnConfig.getDiffOtherColumnNames();
            Iterator<String> diffI = null;
            if (!CoreUtil.isEmpty(diffCols))
            {
                Assert.isTrue(otherCols.size() == diffCols.size(), "对比配置" + getId() + "的DiffOtherColumnName配置不合法！");
                diffI = diffCols.iterator();
            }
            Iterator<String> otherI = otherCols.iterator();
            while (otherI.hasNext())
            {
                String stringOther = otherI.next();
                String stringDiff = diffI == null ? stringOther : diffI.next();
                if (CoreUtil.isEmpty(stringOther))
                {
                    continue;
                }
                result.put(stringOther, stringDiff);
            }
        }
        Set<String> additiveCols = equalsColumnConfig.getAdditiveColumnNames();
        if (!CoreUtil.isEmpty(additiveCols))
        {
            Set<String> diffCols = equalsColumnConfig.getDiffAdditiveColumnNames();
            Iterator<String> diffI = null;
            if (!CoreUtil.isEmpty(diffCols))
            {
                Assert.isTrue(additiveCols.size() == diffCols.size(),
                        "对比配置" + getId() + "的DiffAdditiveColumnName配置不合法！");
                diffI = diffCols.iterator();
            }
            Iterator<String> adiI = additiveCols.iterator();
            while (adiI.hasNext())
            {
                String stringAddi = adiI.next();
                String stringDiff = diffI == null ? stringAddi : diffI.next();
                if (CoreUtil.isEmpty(stringAddi))
                {
                    continue;
                }
                result.put(stringAddi, stringDiff);
            }
        }
        return result;
    }

    /**
     * 获取所有为了匹配的列名
     * @return
     */
    public List<String> getAllMatchColumnName()
    {
        List<String> result = new ArrayList<String>();
        if (equalsColumnConfig != null && !CoreUtil.isEmpty(equalsColumnConfig.getColumnName()))
        {
            result.add(equalsColumnConfig.getColumnName());
        }
        if (levelColumnConfig != null && !CoreUtil.isEmpty(levelColumnConfig.getColumnName()))
        {
            result.add(levelColumnConfig.getColumnName());
        }
        // 使用tableConfig中的结构构建差异原因
        Set<String> otherCols = equalsColumnConfig.getOtherColumnNames();
        if (!CoreUtil.isEmpty(otherCols))
        {
            for (String string : otherCols)
            {
                if (CoreUtil.isEmpty(string))
                {
                    continue;
                }
                result.add(string);
            }
        }
        Set<String> additiveCols = equalsColumnConfig.getAdditiveColumnNames();
        if (!CoreUtil.isEmpty(additiveCols))
        {
            for (String string : additiveCols)
            {
                if (CoreUtil.isEmpty(string))
                {
                    continue;
                }
                result.add(string);
            }
        }
        return result;
    }

    public String getBoundId()
    {
        return boundId;
    }

    public List<CheckColumnConfig> getCheckColumnConfigs()
    {
        return checkColumnConfigs;
    }

    public List<CombineColumnConfig> getCombineColumnConfigs()
    {
        return combineColumnConfigs;
    }

    public List<CompareColumnConfig> getCompareColumnConfigs()
    {
        return compareColumnConfigs;
    }

    public String getCompareMode()
    {
        return compareMode;
    }

    public Set<String> getCompatibleTableNames()
    {
        return compatibleTableNames;
    }

    public List<CoverColumnConfig> getCoverColumnConfigs()
    {
        return coverColumnConfigs;
    }

    public String getDiffColumnKey()
    {
        return diffColumnKey;
    }

    public String getDiffColumnLabel()
    {
        return diffColumnLabel;
    }

    public String getDiffColumnName()
    {
        return diffColumnName;
    }

    public List<DisplayColumnConfig> getDisplayColumns()
    {
        return displayColumns;
    }

    public EqualsColumnConfig getEqualsColumnConfig()
    {
        return equalsColumnConfig;
    }

    public Map<String, Set<String>> getHandSetEquals()
    {
        return handSetEquals;
    }

    public String getId()
    {
        return id;
    }

    public double getLabelLevel()
    {
        return labelLevel;
    }

    public String getLeft()
    {
        return left;
    }

    public LevelColumnConfig getLevelColumnConfig()
    {
        return levelColumnConfig;
    }

    public String getRight()
    {
        return right;
    }

    public String getTableName()
    {
        return tableName;
    }

    public String getTitle()
    {
        return title;
    }

    public TransRowColConfig getTransRowColConfig()
    {
        return transRowColConfig;
    }

    public boolean isHasDiffReason()
    {
        return hasDiffReason;
    }

    public boolean isInsertNoMatch()
    {
        return insertNoMatch;
    }

    public boolean isRecall()
    {
        return recall;
    }

    public void setBoundId(String boundId)
    {
        this.boundId = boundId;
    }

    public void setCheckColumnConfigs(List<CheckColumnConfig> checkColumnConfigs)
    {
        this.checkColumnConfigs = checkColumnConfigs;
    }

    public void setCombineColumnConfigs(List<CombineColumnConfig> combineColumnConfigs)
    {
        this.combineColumnConfigs = combineColumnConfigs;
    }

    public void setCompareColumnConfigs(List<CompareColumnConfig> compareColumnConfigs)
    {
        this.compareColumnConfigs = compareColumnConfigs;
    }

    public void setCompareMode(String compareMode)
    {
        this.compareMode = compareMode;
    }

    public void setCompatibleTableNames(Set<String> compatibleTableNames)
    {
        this.compatibleTableNames = compatibleTableNames;
    }

    public void setCoverColumnConfigs(List<CoverColumnConfig> coverColumnConfigs)
    {
        this.coverColumnConfigs = coverColumnConfigs;
    }

    public void setDiffColumnKey(String diffColumnKey)
    {
        this.diffColumnKey = diffColumnKey;
    }

    public void setDiffColumnLabel(String diffColumnLabel)
    {
        this.diffColumnLabel = diffColumnLabel;
    }

    public void setDiffColumnName(String diffColumnName)
    {
        this.diffColumnName = diffColumnName;
    }

    public void setDisplayColumns(List<DisplayColumnConfig> displayColumns)
    {
        this.displayColumns = displayColumns;
    }

    public void setEqualsColumnConfig(EqualsColumnConfig equalsColumnConfig)
    {
        this.equalsColumnConfig = equalsColumnConfig;
    }

    public void setHandSetEquals(Map<String, Set<String>> handSetEquals)
    {
        this.handSetEquals = handSetEquals;
    }

    public void setHasDiffReason(boolean hasDiffReason)
    {
        this.hasDiffReason = hasDiffReason;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public void setInsertNoMatch(boolean insertNoMatch)
    {
        this.insertNoMatch = insertNoMatch;
    }

    public void setLabelLevel(double labelLevel)
    {
        this.labelLevel = labelLevel;
    }

    public void setLeft(String left)
    {
        this.left = left;
    }

    public void setLevelColumnConfig(LevelColumnConfig levelColumnConfig)
    {
        this.levelColumnConfig = levelColumnConfig;
    }

    public void setRecall(boolean recall)
    {
        this.recall = recall;
    }

    public void setRight(String right)
    {
        this.right = right;
    }

    public void setTableName(String tableName)
    {
        this.tableName = tableName;
    }

    public void setTitle(String title)
    {
        this.title = title;
    }

    public void setTransRowColConfig(TransRowColConfig transRowColConfig)
    {
        this.transRowColConfig = transRowColConfig;
    }
    
    public ColumnLoopTypeEnum getColumnLoopType()
    {
        return columnLoopType;
    }

    public void setColumnLoopType(ColumnLoopTypeEnum columnLoopType)
    {
        this.columnLoopType = columnLoopType;
    }
    
    public List<ExtendColumnConfig> getExtendColumnConfigs()
    {
        return extendColumnConfigs;
    }

    public void setExtendColumnConfigs(List<ExtendColumnConfig> extendColumnConfigs)
    {
        this.extendColumnConfigs = extendColumnConfigs;
    }





    /**
     * 列循环方式
     * @author cuibo
     *
     */
    public enum ColumnLoopTypeEnum
    {
        按列循环,
        按DataTable循环;
        
        public static ColumnLoopTypeEnum valueOfIgnoreNone(String value)
        {
            try
            {
                return valueOf(value);
            } catch (NullPointerException e)
            {
            } catch (IllegalArgumentException e) 
            {
            }
            return null;
        }
    }
}
